from typing import Union, Iterable
from collections import abc


class CAdpu:
    """处理C-ADPU的不可变类"""

    def __init__(self, data: Union[bytes, bytearray, list[int]]):
        """使用全量二进制数据构建C-ADPU"""
        if isinstance(data, bytes):
            self._octets = data
        elif isinstance(data, bytearray) or isinstance(data, list):
            self._octets = bytes(data)
        else:
            raise TypeError(f'C-Adpu构造仅接受bytes,bytearray,List[int]，不接受{type(data)}')

    @staticmethod
    def build(cls: int, ins: int, p1: int, p2: int,
              data: Union[None, bytes, Iterable[int], str] = None, le: int = None) -> 'CAdpu':
        """使用各个部分构建C-ADPU

        其中Lc由data的长度默认给出，当data为None时没有Lc。Le为None时没有Le。
        """
        buffer = bytearray()
        buffer.extend([cls, ins, p1, p2])
        if data:
            if isinstance(data, str):
                octets = bytes.fromhex(data)
                buffer.append(len(octets))  # Lc
                buffer.extend(octets)
            else:
                buffer.append(len(data))  # Lc
                buffer.extend(data)
        if le is not None:
            buffer.append(le)
        return CAdpu(buffer)

    @staticmethod
    def from_hex(hex_str: str):
        """从Hex字符串中恢复出CAdpu"""
        return CAdpu(bytes.fromhex(hex_str))

    @property
    def octets(self) -> bytes:
        """二进制bytes格式的全部数据"""
        return self._octets

    @property
    def value(self) -> list[int]:
        """int数组格式的全部数据，用于smartcard类的命令"""
        return [b for b in self._octets]

    def __repr__(self):
        """Hex字符串表示"""
        return self._octets.hex(' ')


class RAdpu:
    """处理R-ADPU的不可变类"""

    def __init__(self, data: Union[bytes, bytearray, list[int]]):
        """使用全量二进制数据构建C-ADPU"""
        if isinstance(data, bytes):
            self._octets = data
        elif isinstance(data, bytearray) or isinstance(data, list):
            self._octets = bytes(data)
        else:
            raise TypeError(f'R-Adpu构造仅接受bytes,bytearray,list[int]，不接受{type(data)}')

        self._data = self._octets[0:-2]
        self._sw1 = self._octets[-2]
        self._sw2 = self._octets[-1]

    @staticmethod
    def build(data: Union[None, bytes, bytearray, Iterable[int], str], sw1: int, sw2: int) -> 'RAdpu':
        """使用各个部分来构建RAdpu"""
        octets = bytearray()
        if isinstance(data, bytes) or isinstance(data, bytearray) or isinstance(data, abc.Iterable):
            octets.extend(data)
        elif isinstance(data, str):
            octets.extend(bytes.fromhex(data))
        octets.append(sw1)
        octets.append(sw2)
        return RAdpu(octets)

    @property
    def octets(self) -> bytes:
        """bytes格式的全部数据"""
        return self._octets

    @property
    def data(self) -> bytes:
        """bytes格式的响应数据部分"""
        return self._data

    @property
    def sw1(self) -> int:
        """int格式的响应状态字第1字节sw1"""
        return self._sw1

    @property
    def sw2(self) -> int:
        """int格式的响应状态字第1字节sw1"""
        return self._sw2

    @property
    def sw(self) -> bytes:
        """bytes格式的响应状态字，2字节"""
        return bytes([self._sw1, self._sw2])

    @property
    def success(self) -> bool:
        """判断响应是否成功，即SW1 SW2=90 00"""
        return self._sw1 == 0x90 and self._sw2 == 0x00

    def __repr__(self):
        """Hex字符串表示"""
        return self._octets.hex(' ')
